package com.user.config;

import cn.dev33.satoken.exception.*;
import com.common.R;
import com.common.ResultCode;
import com.user.config.Exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.annotation.Priority;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.List;

@RestControllerAdvice
@Slf4j
@Priority(1)
public class AllExceptionHandler {
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public R<List<String>> handleValidatedException(Exception e) {
        String msg = "";
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            msg = ex.getBindingResult().getAllErrors().stream().findFirst().get().getDefaultMessage();
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            msg = ex.getConstraintViolations().stream().findFirst().get().getMessage();
        } else if (e instanceof BindException) {
            BindException ex = (BindException) e;
            msg =ex.getAllErrors().stream().findFirst().get().getDefaultMessage();
        }
        return R.fail(msg);
    }

    @ExceptionHandler(value = {ServiceException.class})
    public R<List<String>> handleServiceException(ServiceException e) {
        return R.fail(e.getCode(),e.getMessage());
    }
    @ExceptionHandler(value = {HttpMessageNotReadableException.class, MethodArgumentTypeMismatchException.class})
    public R<List<String>> handleHttpMessageNotReadableException(Exception e) {
        e.printStackTrace();
        return R.fail(ResultCode.PARAM_FORMAT_ERROR);
    }

    @ExceptionHandler(value = {NotLoginException.class})
    public R<String> handlerNotLoginException(NotLoginException nle) {
        // 不同异常返回不同状态码
        String message = "";
        if (nle.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = "未提供Token";
        } else if (nle.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = "未提供有效的Token";
        } else if (nle.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = "登录信息已过期，请重新登录";
        } else if (nle.getType().equals(NotLoginException.BE_REPLACED)) {
            message = "您的账户已在另一台设备上登录，如非本人操作，请立即修改密码";
        } else if (nle.getType().equals(NotLoginException.KICK_OUT)) {
            message = "已被系统强制下线";
        } else {
            message = "当前会话未登录";
        }
        // 返回给前端
        nle.printStackTrace();
        return R.fail(ResultCode.NON_LOGIN, message);
    }

    @ExceptionHandler(value = {NotRoleException.class,NotPermissionException.class})
    public R<String> handlerNotRoleException(Exception e) {
        String message = "";
        if(e instanceof NotRoleException){
            message = "无此角色：" + ((NotRoleException)e).getRole();
        } else if (e instanceof NotPermissionException) {
            message = "无此权限：" + ((NotPermissionException)e).getCode();
        }
        return R.fail(ResultCode.NON_AUTHOR, message);
    }


    @ExceptionHandler(value = {DisableServiceException.class})
    public  R<String> handlerDisableLoginException(DisableServiceException e) {
        return R.fail(ResultCode.NON_LOGIN, "账户被封禁：" + e.getDisableTime() + "秒后解封");
    }

    @ExceptionHandler(value = {NotSafeException.class})
    public  R<String> handlerNotSafeException(NotSafeException e) {
        return R.fail(ResultCode.NON_LOGIN, "登录环境异常：" + e.getMessage());
    }


}
